package com.ning.cloud.gateway.util;

import com.ning.cloud.gateway.config.JwtProperties;
import com.ning.cloud.gateway.dto.AuthUserDTO;
import io.jsonwebtoken.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Component
public class JwtTokenUtil {

    /**
     * 用户id
     */
    public static final String CLAIM_KEY_USER_ID = "userId";

    /**
     * 用户名
     */
    public static final String CLAIM_KEY_USERNAME = "userName";


    public static final String CLAIM_KEY_CREATED = "createdAt"; //登录时间戳

    @Resource
    private JwtProperties jwtProperties;



    /**
     * 过期毫秒数
     *
     * @return
     */
    public long getExpireMilliseconds() {
        return jwtProperties.getExpires() * 1000;
    }

    /**
     * 生成jwt
     * @param claims
     * @param loginDate 登录时间
     * @return
     */
    public  String generateToken(Map<String, Object> claims, Date loginDate) {
        Date expirationDate = new Date(loginDate.getTime() + this.getExpireMilliseconds()); //过期时间
        return Jwts.builder()
                .setClaims(claims)
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(loginDate)   //签发时间
                .setExpiration(expirationDate) //过期时间
                .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
                .compact();
    }

    /**
     * 由jwttoken解析 用户信息
     * @param jwtToken
     * @return
     */
    public AuthUserDTO parseToken(String jwtToken) {
        AuthUserDTO authUserDTO = null;
        if (StringUtils.isEmpty(jwtToken)) {
            return authUserDTO;
        }

        Claims claims = this.getClaimsFromToken(jwtToken);
        if (claims == null) {
            return authUserDTO;
        }

        String username = claims.get(this.CLAIM_KEY_USERNAME, String.class);
        Long userId = claims.get(this.CLAIM_KEY_USER_ID, Long.class);
        Date LoginDate =  claims.getIssuedAt(); //登录时间
        Date expireDate = claims.getExpiration(); //过期时间

        authUserDTO = new AuthUserDTO();
        authUserDTO.setUserId(userId);
        authUserDTO.setUsername(username);
        authUserDTO.setLoginDate(LoginDate);
        authUserDTO.setExpireDate(expireDate);
        return authUserDTO;
    }


    /**
     * 生成jwt
     * @param claims
     * @return
     */
    public  String generateToken(Map<String, Object> claims) {
        long currentTimeMillis = System.currentTimeMillis();
        Date expirationDate = new Date(currentTimeMillis + this.getExpireMilliseconds()); //过期时间
        Date loginDate = new Date(currentTimeMillis); //登陆时间

        return Jwts.builder()
                .setClaims(claims)
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(loginDate)   //签发时间
                .setExpiration(expirationDate) //过期时间
                .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecret())
                .compact();
    }


    /**
     * 从token中获取登录用户名
     */
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getClaimsFromToken(token);
            username =  claims.get(CLAIM_KEY_USERNAME, String.class);
        } catch (Exception e) {
            username = null;
        }
        return username;
    }

    /**
     * 获取过期时间
     * @param token
     * @return
     */
    public Date getExpirationDateFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        Date expiration = claims.getExpiration();
        return expiration;
    }


    /**
     * 验证token
     * @param authToken
     * @return
     */
    public boolean validateToken(String authToken) {
        try {
            Jwts.parser().setSigningKey(jwtProperties.getSecret()).build().parseClaimsJws(authToken);
            return true;
        } catch (MalformedJwtException e) {
            log.error("Invalid JWT signature", e);
        } catch (ExpiredJwtException e) {
            log.error("Expired JWT token.", e);
        } catch (UnsupportedJwtException e) {
            log.error("Unsupported JWT token.", e);
        } catch (IllegalArgumentException | SignatureException e) {
            log.error("JWT token compact of handler are invalid.", e);
        } catch (Exception e) {
            log.error("token签名错误, token:{}", authToken, e);
        }
        return false;
    }

    /**
     * 获取jwt token信息，解析失败返回null
     * @param token
     * @return
     */
    public Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(jwtProperties.getSecret())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (MalformedJwtException e) {
            log.error("Invalid JWT signature, token:{}", token, e);
        } catch (ExpiredJwtException e) {
            log.error("Expired JWT token. token:{}", token, e);
        } catch (UnsupportedJwtException e) {
            log.error("Unsupported JWT token. token:{}", token, e);
        } catch (IllegalArgumentException | SignatureException e) {
            log.error("JWT token compact of handler are invalid, token:{}", token, e);
        } catch (Exception e) {
            log.error("解析jwt token异常, token:{}", token, e);
        }
        return claims;
    }
}

